package io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.strategy.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.json.JSONUtil;
import io.gitee.itxinmeng.encrypt.spring.boot.autoconfigure.properties.EncryptProperties;
import io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.EncryptMethodFactory;
import io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.strategy.IEncryptStrategy;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

/**
 * @author mx
 */
@Component
//@ConditionalOnProperty(prefix = "custom.encrypt", name = "method", havingValue = "RSA")
public class RsaEncryptStrategyImpl implements IEncryptStrategy, InitializingBean {
    @Resource
    private EncryptProperties config;

    @Override
    public Object encryptBody(Object body, ServerHttpRequest request) {
        String content = JSONUtil.toJsonStr(body);
        byte[] data = content.getBytes(StandardCharsets.UTF_8);
        RSA rsa = getRsa();
        return rsa.encryptHex(data, KeyType.PublicKey);
    }

    @Override
    public String decryptBody(HttpHeaders headers, String content) {
        RSA rsa = getRsa();
        return rsa.decryptStr(content, KeyType.PrivateKey);
    }

    /**
     * Create rsa object
     * @return
     */
    private RSA getRsa(){
        Assert.notBlank(config.getPrivateKey(),"The privateKey are not exist!");
        Assert.notBlank(config.getPublicKey(),"The publicKey are not exist!");
        byte[] privateKey = Base64.decode(config.getPrivateKey());
        byte[] publicKey = Base64.decode(config.getPublicKey());
        return SecureUtil.rsa(privateKey,publicKey);
    }
    @Override
    public Boolean check(){
        String privateKey = config.getPrivateKey();
        String publicKey = config.getPublicKey();
        return StrUtil.isBlank(privateKey) || StrUtil.isBlank(publicKey)? Boolean.FALSE : Boolean.TRUE;
    }

    @Override
    public void afterPropertiesSet() {
        EncryptMethodFactory.INSTANCE.addEncryptStrategy(EncryptMethodFactory.EncryptMethodEnum.RSA,this);
    }
}
